package com.mt.common.system.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSONObject;
import com.mt.common.core.utils.ScheduledUtils;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @author zhanghong
 * @date 2023-04-22 18:49
 */
@Service(value = "dBBackup")
public class DBBackup implements InitializingBean {
    Logger logger = LoggerFactory.getLogger(DBBackup.class);
    /**
     * 文件后缀
     */
    public static final String FILE_SUFFIX = ".sql";

    /**
     * 判断操作系统类型、Linux|Windows
     */
    public static boolean isSystem(String osName) {
        Boolean flag = null;
        if (osName.startsWith("windows")) {
            flag = true;
        } else if (osName.startsWith("linux")) {
            flag = false;
        }
        return flag;
    }

    public void mysqlBackups(String jsonParam) throws JobExecutionException, IOException {
        JSONObject jsonObject = JSONObject.parseObject(jsonParam);
        String ip = jsonObject.getString("ip");
        String port = jsonObject.getString("port");
        String database_name = jsonObject.getString("database_name");
        String userName = jsonObject.getString("userName");
        String password = jsonObject.getString("password");
        String backupPath = jsonObject.getString("backupPath");
        Boolean isDocker = jsonObject.getBoolean("isDocker");
        // 数据库文件名称
        StringBuilder mysqlFileName = new StringBuilder()
                .append(database_name)
                .append("_")
                .append(DateUtil.format(new Date(), "yyyy-MM-dd-HH-mm-ss"))
                .append(FILE_SUFFIX);
        //File file = new File(backupPath + mysqlFileName.toString());
        //if (!file.exists()) {
        //    file.createNewFile();
        //}
        // 备份命令
        StringBuilder cmd = new StringBuilder();
        if (isDocker) {
            cmd.append("docker exec -i mysql ");
        }
        cmd.append("mysqldump ")
                .append("--no-tablespaces ")
                .append("-h")
                .append(ip)
                .append(" -P")
                .append(port)
                .append(" -u")
                .append(userName)
                .append(" -p")
                .append(password)
                .append(" --default-character-set=utf8mb4").append(" --hex-blob")
                // 排除MySQL备份表
                .append(" --ignore-table ")
                .append(database_name)
                .append(".sys_login_record ")
                .append(database_name)
                .append(" >")
                .append(backupPath)
                .append(mysqlFileName);
        // 判断文件是否保存成功
        if (!FileUtil.exist(backupPath)) {
            FileUtil.mkdir(backupPath);
            throw new JobExecutionException("备份失败，文件保存异常，请查看文件内容后重新尝试！");
        }
        logger.info("备份命令："+cmd);
        // 获取操作系统名称
        String osName = System.getProperty("os.name").toLowerCase();
        String[] command = null;
        if (isSystem(osName)) {
            // Windows
            command = new String[]{"cmd", "/c", String.valueOf(cmd)};
        } else {
            // Linux
            command = new String[]{"/bin/sh", "-c", String.valueOf(cmd)};

        }
        //log.error("数据库备份命令为：{}", cmd);
        // 获取Runtime实例
        Process process = null;
        try {
            process = Runtime.getRuntime().exec(command);
            if (process.waitFor() == 0) {
                logger.info("Mysql 数据库备份成功,备份文件名：{}", mysqlFileName);
                /*
                删除文件
                 */
            } else {
                logger.error("网络异常，数据库备份失败,代码为" + cmd);
                throw new JobExecutionException("网络异常，数据库备份失败,指令为" + cmd);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("网络异常，数据库备份失败,代码为" + cmd);
            throw new JobExecutionException("网络异常，数据库备份失败,指令为" + cmd);
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        String name = this.getClass().getSimpleName();
        Method[] declaredMethods = this.getClass().getDeclaredMethods();
        List<String> res = new ArrayList<>();
        Set<String> ignored = new HashSet<>();
        ignored.add("afterPropertiesSet");
        ignored.add("isSystem");
        for (int i = 0; i < declaredMethods.length; i++) {
            if (!ignored.contains(declaredMethods[i].getName())) {
                res.add(declaredMethods[i].getName());
            }
        }
        char[] cs = name.toCharArray();
        cs[0] += 32;
        name = new String(cs);
        ScheduledUtils.serviceMap.put(name, res);
    }
}
